﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Threading;
using System.Text.RegularExpressions;
using System.IO;
using System.Security.Cryptography;
using System.Configuration;
using System.Diagnostics;
using System.Net;
using System.Collections;
using System.Collections.Specialized;
using XmHttpServer;
using System.Reflection;



namespace XmHttpServerForm
{
    public partial class MainForm : Form
    { 
        public static MainForm mainForm = null;

        private HttpServer server;
        private ConsoleWriter log = new ConsoleWriter();

        public MainForm()
        {
            Application.EnableVisualStyles();
            InitializeComponent();
            //解决线程间操作无效
            Control.CheckForIllegalCrossThreadCalls = false;
            server = new HttpServer();
            server.StateChanged+=new EventHandler(server_StateChanged);
            server.RequestReceived += new HttpRequestEventHandler(server_RequestReceived);
            server.ClientConnected += new ClientEventHandler(server_ClientConnected);
            server.ClientDisconnected += new ClientEventHandler(server_ClientDisconnected);
            log.OnWrite += new ConsoleWriter.WriteEventHandler(writer_OnWrite);
            server.Log = log;
            Assembly ab = Assembly.GetExecutingAssembly();//获取当前运行的程序集
            server.Assembly = ab;
            server.addDirectory("/StartupPath", Application.StartupPath);

            server_StateChanged(this, null);

            //初始化设置
            //设置是否启用rest安全性
            setRequireAuthentication("true".Equals(Tools.configGetValue("RequireAuthentication")) ? true : false);
            //设置日志是否记录到文件
            setIsLogToFile("true".Equals(Tools.configGetValue("IsLogToFile")) ? true : false);
            //设置日志是否记录到日志记录框
            setIsLogToTextBox("true".Equals(Tools.configGetValue("IsLogToTextBox")) ? true : false);
        }

        void server_ClientDisconnected(object sender, HttpClientEventArgs e)
        {
            log.WriteLine("[" + DateTime.Now + "]"  + " Disconnected: " + e.HttpClient.RemoteAddress());
        }

        public void server_ClientConnected(object sender, HttpClientEventArgs e)
        {
            log.WriteLine("[" + DateTime.Now + "]"  + " Connected: " + e.HttpClient.RemoteAddress());
        }

        void server_RequestReceived(object sender, HttpRequestEventArgs e)
        {
            log.WriteLine("[" + DateTime.Now + "]" + " Request: " + e.Request.Url );
        }

        private void server_StateChanged(object sender, EventArgs e)
        {
            if (InvokeRequired)
            {
                Invoke(new EventHandler(server_StateChanged), new object[] { sender, e });
                return;
            }

            btnStart.Enabled = !(server.State == HttpServerState.Started || server.State == HttpServerState.Starting);
            btnStop.Enabled = (server.State == HttpServerState.Started);

            //if (server.IsRunning)
            //    notifyIcon.Text = "XmServer - running on port " + server.Port;
            //else
            //    notifyIcon.Text = "XmServer";
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(txtPort.Text))
            {
                bool isUse = Tools.isPortInUse("9090");
                if (isUse)
                {
                    MessageBox.Show("端口已被占用，请使用其他端口");
                    return;
                }
                if(cboAddressList.SelectedIndex == -1)
                {
                    MessageBox.Show("请选择一个ip地址");
                    return;
                }
                IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(cboAddressList.SelectedItem.ToString()), 9090);
                server.EndPoint = endPoint;
                
                Tools.configSetValue("Port", "9090");
            }
            else if (!Tools.isNumber(txtPort.Text))
            {
                MessageBox.Show("请填写正确的数字端口");
                return;
            }
            else
            {
                bool isUse = Tools.isPortInUse(txtPort.Text);
                if (isUse)
                {
                    MessageBox.Show("端口已被占用，请使用其他端口");
                    return;
                }
                IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(cboAddressList.SelectedItem.ToString()), Convert.ToInt32(txtPort.Text));
                server.EndPoint = endPoint;
                Tools.configSetValue("Port",txtPort.Text);
            }
            
            //加入用户
            (server.Authenticator as BasicAuthenticator).RemoveAllUser();
            //(server.Authenticator as BasicAuthenticator).AddUser("test", "test"); //加入一个预置的用户 密码1234
            //从配置文件中读取用户并添加到server中
            NameValueCollection userNv = Tools.configGetAllUserValue();
            foreach (string userName in userNv)
            {
                (server.Authenticator as BasicAuthenticator).AddUser(userName,userNv[userName]); 
            }
            
            server.Start();
            btnStart.Enabled = false;
            btnStop.Enabled = true;
            Tools.configSetValue("Ip", cboAddressList.SelectedItem.ToString());
        }

        public void setRequireAuthentication(bool isAuth)
        {
            server.RequireAuthentication = isAuth; //是否需要认证
        }
        private bool isLogToTextBox = true;
        public void setIsLogToTextBox(bool isLogTo)
        {
            isLogToTextBox = isLogTo;
        }
        private bool isLogToFile = true;
        public void setIsLogToFile(bool isLogTo)
        {
            isLogToFile = isLogTo;
        }
        public void Log(string str)
        {
            log.WriteLine(str);
        }
        
        private void btnStop_Click(object sender, EventArgs e)
        {
            if (server != null)
            {
                if (server.State != HttpServerState.Stopped && server.State != HttpServerState.Stopping)
                {
                    server.Stop();
                }
            }
        }
        

        
        
         
        private void frmMain_Load(object sender, EventArgs e)
        {
            mainForm = this;
            string port = Tools.configGetValue("Port");
            if (!string.IsNullOrEmpty(port))
            {
                txtPort.Text = port;
            }
            System.Net.IPHostEntry ipEntry = System.Net.Dns.GetHostEntry(Dns.GetHostName());
            System.Net.IPAddress[] addressList = ipEntry.AddressList;
            string ip = Tools.configGetValue("Ip");
            int selectedIndex = -1;
            int idx = 0;
            foreach (IPAddress address in addressList)
            {
                if (address.ToString().IndexOf(".") > -1)
                {
                    if (address.ToString().Equals(ip))
                    {
                        selectedIndex = idx;
                    }
                    cboAddressList.Items.Add(address.ToString());
                    idx++;
                }
            }
            if (cboAddressList.Items.Count > 0)
            {
                if (selectedIndex == -1)
                {
                    cboAddressList.SelectedIndex = cboAddressList.Items.Count - 1;
                }
                else
                {
                    cboAddressList.SelectedIndex = selectedIndex;
                }
                
            }
           
            //是否自动启动
            string isAutoRun = Tools.configGetValue("IsAutoRun");
            if ("true".Equals(isAutoRun))
            {
                btnStart_Click(null, null);
            }
            
            
        }
        
        /// <summary>
        /// 启动服务器
        /// </summary>
        /// <returns></returns>
        public string startServer()
        {
            try
            {
                btnStart_Click(null, null);
                return "服务器已启动成功!";
            }
            catch (Exception ex)
            {
                string className = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.ToString();
                string methodName = System.Reflection.MethodBase.GetCurrentMethod().Name;
                ex.Source = "错误源：" + className + " " + "调用方法：" + methodName;
                Tools.Log(ex);
                return ex.Source + "  错误信息：" + ex.Message;
            }
        }
        /// <summary>
        /// 停止服务器
        /// </summary>
        /// <returns></returns>
        public string stopServer()
        {
            try
            {
                btnStop_Click(null, null);
                return "服务器已停止!";
            }
            catch (Exception ex)
            {
                string className = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.ToString();
                string methodName = System.Reflection.MethodBase.GetCurrentMethod().Name;
                ex.Source = "错误源：" + className + " " + "调用方法：" + methodName;
                Tools.Log(ex);
                return ex.Source + "  错误信息：" + ex.Message;
            }
        }
        

        private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (server != null)
            {
                if (server.State != HttpServerState.Stopped && server.State != HttpServerState.Stopping)
                {
                    server.Stop();
                }
                server.Dispose();
            }
        }
 
        private void btnHomeUrl_Click(object sender, EventArgs e)
        {
            if (btnStart.Enabled==false)
            {
                try
                {
                    using (Process process = new System.Diagnostics.Process())
                    {
                        process.StartInfo.FileName = @"http://"+cboAddressList.SelectedItem.ToString()+":" + txtPort.Text;
                        process.StartInfo.CreateNoWindow = false;
                        process.Start();
                        process.Dispose();
                    }
                }
                catch (System.ComponentModel.Win32Exception noBrowser)
                {
                    if (noBrowser.ErrorCode == -2147467259)
                        MessageBox.Show(noBrowser.Message, "系统提示");
                }
                catch (System.Exception other)
                {
                    MessageBox.Show(other.Message, "系统提示");
                }
                
            }
            else
            {
                MessageBox.Show("请先启动服务器!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }

        private void btnSetting_Click(object sender, EventArgs e)
        {
            SettingForm frm = new SettingForm();
            frm.ShowDialog(this);
        }


        //*************************记录log日志******************************
        StreamWriter logWriter;
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        static internal extern IntPtr SendMessage(IntPtr hwnd, Int32 msg, Int32 wParam, Int32 lParam);

        bool newLine;
        delegate void OnWriteDelegate(char[] buffer, int index, int count);
        private void writer_OnWrite(char[] buffer, int index, int count)
        {
            if (InvokeRequired)
            {
                Invoke(new OnWriteDelegate(writer_OnWrite), new object[] { buffer, index, count });
                return;
            }

            if (outputBox.IsDisposed)
                return;

            if (isLogToFile)
            {
                if (logWriter == null)
                {
                    try
                    {
                        FileStream stream = new FileStream("request.log", FileMode.Append, FileAccess.Write, FileShare.Read, 128);
                        logWriter = new StreamWriter(stream);
                        logWriter.AutoFlush = true;

                        logWriter.WriteLine("-------------------------------------------------------");
                        logWriter.WriteLine("* Beginning log at " + DateTime.Now);
                        logWriter.WriteLine("-------------------------------------------------------");
                    }
                    catch { }
                }

                logWriter.Write(buffer, index, count);
            }

            string text = new string(buffer, index, count);

            if (text.Length == 0)
                return;

            bool oldNewLine = newLine;

            newLine = false;

            if (text.EndsWith("\r\n"))
            {
                text = text.Substring(0, text.Length - 2);
                newLine = true;
            }

            else if (text.EndsWith("\n"))
            {
                text = text.Substring(0, text.Length - 1);
                newLine = true;
            }
            if (isLogToTextBox)
            {
                outputBox.AppendText((oldNewLine ? "\r\n" : "") + text);
            }
            

            // Scroll to bottom
            SendMessage(this.outputBox.Handle, 0x0115, 7, 0);
        }
        //*************************记录log日志******************************

        private void outputBox_LinkClicked(object sender, System.Windows.Forms.LinkClickedEventArgs e)
        {
            try
            {
                using (Process process = new System.Diagnostics.Process())
                {
                    process.StartInfo.FileName = @e.LinkText;
                    process.StartInfo.CreateNoWindow = false;
                    process.Start();
                    process.Dispose();
                }
            }
            catch (Win32Exception)
            {
            }
        }

      

        private void 清除日志ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            outputBox.Clear();
        }

        private void btnAbout_Click(object sender, EventArgs e)
        {
            AboutForm frm = new AboutForm();
            frm.ShowDialog(this);
        }
  

         
        
    }
}
